﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using Csla.Core;

namespace NetFrameworkExtensions.BusinessLayer.Csla4
{
  public abstract class CslaBusinessListBase<TEntity, TList, TIdentified, TIdentifier> :
    BusinessListBase<TList, TIdentified>,
    ICslaBusinessList<TEntity, TIdentified, TIdentifier>,
    IItemContainer<TIdentified, TIdentifier>,
    IItemContainer<TIdentifier>,
    IItemContainer,
    IAccessibleList
    where TEntity : class, IIdentified<TIdentified, TIdentifier>
    where TList : CslaBusinessListBase<TEntity, TList, TIdentified, TIdentifier>
    where TIdentified : CslaBusinessChildBase<TEntity, TIdentified, TIdentifier>
    where TIdentifier : IEquatable<TIdentifier>
  {
    #region [ IBusinessBase ]
    IBusinessBase IBusinessBase.Parent
    {
      get { return Parent as IBusinessBase; }
    }
    #endregion

    #region [ IAccessibleList ]
    public abstract bool CanRead { get; }

    public abstract bool CanCreate { get; }

    public abstract bool CanUpdate { get; }

    public abstract bool CanDelete { get; }
    #endregion

    #region [ IItemContainer ]

    protected abstract TIdentified CreateChildFrom(TEntity item);

    IIdentified<TIdentified, TIdentifier> IItemContainer<TIdentified, TIdentifier>.CreateFrom(IIdentified<TIdentified, TIdentifier> item)
    {
      if (item is TEntity)
      {
        var result = CreateChildFrom((TEntity)item);
        Add(result);
        return result;
      }
      return null;
    }

    IIdentified<TIdentified, TIdentifier> IItemContainer<TIdentified, TIdentifier>.RemoveFrom(IIdentified<TIdentified, TIdentifier> item)
    {
      if (item is TEntity)
      {
        var local = this.Where(l => l.Identifier.Equals(item.Identifier)).Cast<TIdentified>().FirstOrDefault();
        if (local != null)
          using (RaiseListChangedEvents.SetWithRestore(true, v => RaiseListChangedEvents = v))
          {
            Remove(local);
            DeletedList.Remove(local);
            return local;
          }
      }
      return null;
    }

    IIdentified<TIdentifier> IItemContainer<TIdentifier>.CreateFrom(IIdentified<TIdentifier> item)
    {
      return ((IItemContainer<TIdentified, TIdentifier>)this).CreateFrom((IIdentified<TIdentified, TIdentifier>)item);
    }

    IIdentified<TIdentifier> IItemContainer<TIdentifier>.RemoveFrom(IIdentified<TIdentifier> item)
    {
      return ((IItemContainer<TIdentified, TIdentifier>)this).RemoveFrom((IIdentified<TIdentified, TIdentifier>)item);
    }

    IIdentified IItemContainer.CreateFrom(IIdentified item)
    {
      return ((IItemContainer<TIdentified, TIdentifier>)this).CreateFrom((IIdentified<TIdentified, TIdentifier>)item);
    }

    IIdentified IItemContainer.RemoveFrom(IIdentified item)
    {
      return ((IItemContainer<TIdentified, TIdentifier>)this).RemoveFrom((IIdentified<TIdentified, TIdentifier>)item);
    }
    #endregion

    #region [ IBusinessList ]
    object IBusinessList.AddNew()
    {
      return this.AddNew();
    }
    #endregion
  }
}
